package de.koller.oceanFramework.util;

import de.koller.oceanFramework.OceanException;
import java.util.HashSet;
import java.util.Set;

public class LightWeightNode<T> implements ILightWeightNode<T> {
	
	public T root;
	public ILightWeightNode<T> mother;
	
	private final Set< ILightWeightNode<T> > set = new HashSet<>();
	private boolean valid = true;
	private boolean locked = false;

	@Override
	public void generate( T root, Object... references ) {
		this.root = root;
		valid = true;
		locked = false;
	}
	
	@Override
	public void ungenerate() {
		for( ILightWeightNode<T> n : set )
			n.ungenerate();
		valid = false;
		locked = true;
		
		mother = null;
	}

	@Override
	public void addNode( ILightWeightNode<T> node, Object... references ) {
		if( !isValid() ) throw new OceanException( "First generate the node to add an other" );
		if( locked ) throw new OceanException( "can't add during an update" );
		node.generate( root, references );
		set.add( node );
		
		if( node instanceof LightWeightNode<?> )
			((LightWeightNode<T>)node).mother = this;
	}

	public void removeNode( ILightWeightNode<T> node ) {
		if( locked )
			throw new OceanException( "node is locked!" );
		
		if( !set.remove( node ) )
			throw new OceanException( "cannot find node to remove!" );
		
		node.ungenerate();
	}
	
	protected void update( Object... refernces ) {
		
	}
	
	protected void updateAfter() {
		
	}
	
	@Override
	public final void updateNode( Object... references ) {
		locked = true;
		
		this.update( references );
		for( ILightWeightNode<T> node : set )
			node.updateNode( references );
		this.updateAfter();
		
		locked = false;
	}
	
	final public boolean isValid() {
		return valid;
	}
	
	public int getNumberOfNodes() {
		return set.size();
	}

	public ILightWeightNode<T> getMother() {
		return mother;
	}
	
}
